﻿using System;
using System.Net;
using FreeSwitch.EventSocket.Commands;
using FreeSwitch.EventSocket.Events;
using FreeSwitch.EventSocket.Parser;

namespace FreeSwitch.EventSocket
{
	public class EventSocket
	{
		private readonly string _password;
		private readonly EventChannel _client;
		private readonly CommandDispatcher _dispatcher;
		private readonly EventDispatcher _eventDispatcher;
		private readonly ILogger _logger = LogManager.GetLogger(typeof (EventSocket));

		public EventSocket(IPEndPoint endPoint, string password)
		{
			_password = password;
			_client = new EventChannel(endPoint);
			_client.MessageReceived += OnRawMessage;
			_dispatcher = new CommandDispatcher(_client);
			_eventDispatcher=new EventDispatcher();
			
		}

		/// <summary>
		/// Gets or sets if we are authenticated.
		/// </summary>
		public bool IsAuthenticated { get; set; }

		private void OnRawMessage(object sender, MessageEventArgs e)
		{
			switch (e.Message.Headers["Content-Type"])
			{
				case "text/event-plain":
					_eventDispatcher.Process(e.Message);
					break;
				case "command/reply":
				case "api/response":
					_dispatcher.Process(e.Message);
					break;

				case "auth/request":
					//IsAuthenticated = Authenticate("ClueCon");
					BeginSendCommand(new Authenticate(_password), OnAuthenticate, null);
					break;

				case "text/disconnect-notice":
					_logger.Warning(e.Message.Body.ToString());
					break;

				default:
					_logger.Warning("Failed to find handler for content-type:" + e.Message.Headers["Content-Type"]);
					break;
			}
		}

		private void OnAuthenticate(IAsyncResult ar)
		{
			ICommandReply cmd = EndSendCommand(ar);
			IsAuthenticated = ((CommandReply) cmd).Success;
			BeginSendCommand(new Subscribe("ALL"), null, null);
		}

		public IAsyncResult BeginSendCommand(ICommand command, AsyncCallback callback, object state)
		{
			return _dispatcher.BeginSend(command, callback, state);
		}

		public ICommandReply EndSendCommand(IAsyncResult result)
		{
			return _dispatcher.EndSend(result);
		}

		public ICommandReply SendCommand(ICommand command)
		{
			IAsyncResult result = _dispatcher.BeginSend(command, null, null);
			return _dispatcher.EndSend(result);
		}


		public void Start()
		{
			_client.Start();
		}
	}

	public class EventReceivedEventArgs : EventArgs
	{
		public EventReceivedEventArgs(Event theEvent)
		{
		}
	}
}